import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.regex.Pattern;

public class lexAnalyse {
    private HashMap<String, String> keywords = new HashMap<>();
    private HashMap<String, String> symbols = new HashMap<>();
    private int pointer;

    public lexAnalyse() {
        init();
    }

    public void init() {
        //关键字
        keywords.put("main", "Main");
        keywords.put("if", "If");
        keywords.put("else", "Else");
        keywords.put("while", "While");
        keywords.put("break", "Break");
        keywords.put("continue", "Continue");
        keywords.put("return", "Return");
        keywords.put("int", "Int");
        keywords.put("void", "Void");
        keywords.put("const", "Const");
        //符号
        symbols.put("=", "Assign");
        symbols.put(";", "Semicolon");
        symbols.put("(", "LPar");
        symbols.put(")", "RPar");
        symbols.put("[", "LBracket");
        symbols.put("]", "RBracket");
        symbols.put("{", "LBrace");
        symbols.put("}", "RBrace");
        symbols.put("+", "Plus");
        symbols.put("-", "Minus");
        symbols.put("*", "Mult");
        symbols.put("/", "Div");
        symbols.put("<", "Lt");
        symbols.put(">", "Gt");
        symbols.put("%", "Mod");
        symbols.put("!", "Not");
        symbols.put("==", "Eq");
        symbols.put("!=", "NotEq");
        symbols.put(">=", "GreatEq");
        symbols.put("<=", "LessEq");
        symbols.put("||", "Or");
        symbols.put("&&", "And");
        symbols.put(",", "Comma");
    }

    public ArrayList<String> analyse(String s) {
        ArrayList<String> token = new ArrayList<>();
        pointer = 0;
        s = s.trim();
        char c;
        while (pointer < s.length()) {
            c = s.charAt(pointer);
            if (Character.isDigit(c)) {
                checkDigit(s, token);
            } else if (Character.isLetter(c) || c == '_') {
                checkLetter(s, token);
            } else if (Pattern.compile("\\s").matcher(c + "").matches()) {
                pointer++;
            } else {
                checkSymbol(s, token);
            }
        }
        return token;
    }

    //匹配数字
    public void checkDigit(String s, ArrayList<String> token) {
        StringBuilder re = new StringBuilder();
        if (s.charAt(pointer) == '0' && (s.charAt(pointer + 1) == 'x' || s.charAt(pointer + 1) == 'X')) {
            pointer += 2;
            re.append("0x");
            while (pointer < s.length() && (Character.isDigit(s.charAt(pointer)) ||
                    Pattern.compile("[a-fA-F]").matcher(s.charAt(pointer) + "").matches())) {
                re.append(s.charAt(pointer++));
            }
        } else {
            while (pointer < s.length() && Character.isDigit(s.charAt(pointer))) {
                re.append(s.charAt(pointer++));
            }
        }
        int n;
        if (re.toString().startsWith("0x")) {
            n = Integer.parseInt(re.substring(2).toUpperCase(Locale.ROOT), 16);
        } else if (re.toString().startsWith("0") && re.toString().length() > 1) {
            n = Integer.parseInt(re.substring(1), 8);
        } else {
            n = Integer.parseInt(re.toString(), 10);
        }
        token.add("Number(" + n + ")");
    }

    //匹配标识符
    public void checkLetter(String s, ArrayList<String> token) {
        StringBuilder re = new StringBuilder();
        re.append(s.charAt(pointer++));
        while (pointer < s.length() && (Character.isLetterOrDigit(s.charAt(pointer)) || s.charAt(pointer) == '_')) {
            re.append(s.charAt(pointer++));
        }
        if (isKeyword(re.toString())) {
            token.add(keywords.get(re.toString()));
        } else {
            token.add("Ident(" + re.toString() + ")");
        }
    }

    //匹配符号
    public void checkSymbol(String s, ArrayList<String> token) {
        char[] c = new char[2];
        boolean flag;
        c[0] = s.charAt(pointer);
        if (pointer + 1 < s.length()) {
            c[1] = s.charAt(pointer + 1);
            flag = true;
        } else {
            flag = false;
        }
        String str = String.valueOf(c);
        if (flag && symbols.containsKey(str)) {
            token.add(symbols.get(str));
            pointer += 2;
        } else if (symbols.containsKey(c[0] + "")) {
            token.add(symbols.get(c[0] + ""));
            pointer++;
        } else {
            System.out.println("CheckSymbol:未找到匹配的符号-->\" " + c[0] + " \"");
            System.exit(1);
        }
    }

    public Boolean isKeyword(String s) {
        return keywords.containsKey(s);
    }
}
